﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Common;
using Common.Views;
using DataAccess;

namespace BL_WServices
{
    /// <summary>
    /// This is the WCF Service which is implementing the interface IProductsService
    /// </summary>
    public class ProductsService : IProductsService
    {
        
        /// <summary>
        /// Get all the Products from the database
        /// </summary>
        /// <returns>Returns all the Products within the Products Entity.</returns>
        public IQueryable<Product> GetAllProducts()
        {
            return new ProductsRepository().GetAllProducts();
        }

        /// <summary>
        /// Gets all the comments for a particular product
        /// </summary>
        /// <param name="productID">Used to get comments for a particular product</param>
        /// <returns>Returns a list of comments by productID</returns>
        public IQueryable<ProductComment> GetCommentsByProductID(int productID)
        {
            return new ProductsRepository().GetCommentsByProductID(productID);
        }

        /// <summary>
        /// Get all the products from the database through the productID
        /// </summary>
        /// <param name="productID">Of type int. The product is returned from the database 
        /// through the productID.</param>
        /// <returns>Returns the Product by its ID</returns>
        public Product GetProductById(int productID)
        {
            return new ProductsRepository().GetProductById(productID);
        }

        /// <summary>
        /// Add Products to Cart Entity using the Username, Product ID and Quantity
        /// </summary>
        /// <param name="username">Username of the customer who added products to cart</param>
        /// <param name="productId">ProductID of the product added to cart</param>
        /// <param name="qty">Quantity number of ProductID added to cart</param>
        public string AddToCart(string username, int productId, int qty)
        {
            ProductsRepository pr = new ProductsRepository();
            Product p = pr.GetProductById(productId);

            if (p.StockQty >= qty)
            {
                Cart sc = pr.GetCart(username, productId);
                if (sc == null)
                {
                    Cart c1 = new Cart()
                    {
                        Username = username,
                        ProductID = productId,
                        ProductQty = qty
                    };
                    pr.AddToCart(c1);
                    return null;
                }
                else
                {
                    if (sc.ProductID == productId)
                    {
                        pr.UpdateCart(username, productId, qty);
                        return null;
                    }
                    else
                    {
                        Cart c2 = new Cart()
                        {
                            Username = username,
                            ProductID = productId,
                            ProductQty = qty
                        };
                        pr.AddToCart(c2);
                        return null;
                    }
                }
            }
            else
            {
                return "not enough stock";
            }
        }

        /// <summary>
        /// Add comment to a particular product
        /// </summary>
        /// <param name="username">Of type string. Username who entered the comment</param>
        /// <param name="productID">Of type int. ProductID that has a new comment associated to it</param>
        /// <param name="comment">Of type string. The actual comment</param>
        public void AddComment(string username, int productID, string comment)
        {
            ProductsRepository pr = new ProductsRepository();

            ProductComment pc = new ProductComment()
            {
                Username = username,
                ProductID = productID,
                Comment = comment,
                Date = DateTime.Now
            };
            pr.AddComment(pc);
        }

        /// <summary>
        /// Return the products from the Cart Entity depending on the username
        /// </summary>
        /// <param name="username">Used to get the products from the cart entity depending on the username</param>
        /// <returns></returns>
        public IQueryable<CartView> GetProductsFromCart(string username)
        {
            return new ProductsRepository().GetProductsFromCart(username);
        }

        /// <summary>
        /// Returns the average rating of a product
        /// </summary>
        /// <param name="productID">Of type int. Used to get the the average rating for that product</param>
        /// <returns>Returns IQueryable int - Returns the average rating of a product</returns>
        public IQueryable<int> ReturnAverageRating(int productID)
        {
            return new ProductsRepository().ReturnAverageRating(productID);
        }

        /// <summary>
        /// Add rating by username, productID and the rating number
        /// </summary>
        /// <param name="username">Of type string. The username that will add the rating</param>
        /// <param name="productId">Of type int. The productID that will have the rating</param>
        /// <param name="rating">Of type int. The number that will be added to rate the product</param>
        /// <returns>Returns a string message rated if already rated</returns>
        public string AddProductRating(string username, int productId, int rating)
        {
            ProductsRepository r = new ProductsRepository();
            if (r.GetUserRatings(username, productId).Count() > 0)
            {
                return "rated";
            }
            else
            {
                ProductRating pr = new ProductRating();
                pr.Username = username;
                pr.ProductID = productId;
                pr.RatingNo = rating;
                r.AddProductRatings(pr);

                return null;
            }
        }

        /// <summary>
        /// Return the product details of a product
        /// </summary>
        /// <param name="productID">Of tyep int. Used to get the product details from the database</param>
        /// <param name="orderID">Of type guid. Used to get the product details by orderID</param>
        /// <returns>Returns the product details from the database depending on the productID </returns>
        public OrdersView GetProductDetails(int productID, Guid orderID)
        {
            return new ProductsRepository().GetProductDetails(productID, orderID);
        }

        /// <summary>
        /// Get all the Categories from the Table Categories
        /// </summary>
        /// <returns>Returns a list of categories</returns>
        public IEnumerable<Category> GetCategories()
        {
            return new ProductsRepository().GetCategories();
        }

        /// <summary>
        /// Return a list of products depending on their categoryID
        /// </summary>
        /// <param name="categoryID">Of type int. Used to get a list of products depending on the categoryID</param>
        /// <returns>Returns a list of products</returns>
        public IQueryable<Product> GetProductsByCategoryRefinement(int categoryID)
        {
            return new ProductsRepository().GetProductsByCategoryRefinement(categoryID);
        }

        /// <summary>
        /// Returns a list of products depending on their product name
        /// </summary>
        /// <param name="keyword">Of type string. Used to return a list of products depending on the name</param>
        /// <returns>Returns a list of products</returns>
        public IEnumerable<Product> SearchProductByName(string keyword)
        {
            return new ProductsRepository().SearchProductByName(keyword);
        }

        /// <summary>
        /// Returns a list of products depending on the price
        /// </summary>
        /// <param name="minPrice">Of type decimal. </param>
        /// <param name="maxPrice">Of type decimal. </param>
        /// <returns>Returns a list of products depending on the minimum Price and maximum Price</returns>
        public IEnumerable<Product> SearchProductByPrice(decimal minPrice, decimal maxPrice)
        {
            return new ProductsRepository().SearchProductByPrice(minPrice, maxPrice);
        }

        /// <summary>
        /// Returns a list of products in ascending order
        /// </summary>
        /// <returns>Returns a list of products in ascending order, ordered by the price</returns>
        public IEnumerable<Product> SearchProductByPriceASC()
        {
            return new ProductsRepository().SearchProductByPriceASC();
        }

        /// <summary>
        /// Returns a list of products in descending order
        /// </summary>
        /// <returns>Returns a list of products in descending order, ordered by the price</returns>
        public IEnumerable<Product> SearchProductByPriceDESC()
        {
            return new ProductsRepository().SearchProductByPriceDESC();
        }

        /// <summary>
        /// Returns a list of products in descending order
        /// </summary>
        /// <returns>Returns a list of products in descending order, ordered by the date</returns>
        public IEnumerable<Product> SearchProductByDateASC()
        {
            return new ProductsRepository().SearchProductByDateASC();
        }

        /// <summary>
        /// Returns a list of products by username
        /// </summary>
        /// <param name="username">Of type string. Used to get the products by username</param>
        /// <returns></returns>
        public IQueryable<CartView> GetAllProductsByUsername(string username)
        {
            return new ProductsRepository().GetAllProductsByUsername(username);
        }

    }
}
